package com.vidmt.api.modules.sys.api;

import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.thinkgem.jeesite.modules.sys.utils.UserUtils;
import com.vidmt.api.common.anno.ApiDoc;
import com.vidmt.api.common.pojo.ApiResultServer;
import com.vidmt.api.common.utils.DateUtil;
import com.vidmt.api.common.utils.GeoUtil;
import com.vidmt.api.common.web.ApiController;
import com.vidmt.api.modules.sys.Enums.TraceReason;
import com.vidmt.api.modules.sys.entity.Location;
import com.vidmt.api.modules.sys.entity.Trace;
import com.vidmt.api.modules.sys.entity.User;
import com.vidmt.api.modules.sys.service.LocationService;
import com.vidmt.api.modules.sys.service.TraceService;
import com.vidmt.api.modules.sys.service.UserService;

@Controller
@ResponseBody
@RequestMapping("/api/1/location")
public class ApiLocationController extends ApiController {
	private static final Logger log = LoggerFactory.getLogger(ApiLocationController.class);
	@Autowired
	private LocationService locationService;
	@Autowired
	private TraceService traceService;
	@Autowired
	private UserService userService;

	// 因为定时任务暂时不可用，在此处判定是否清空足迹缓存
	// @Autowired
	// private SaveCacheTask saveCacheTask;

	@RequestMapping("/upload.*")
	public ApiResultServer uploadLocation(Location loc) {
		User user = UserUtils.getCurrentUser();
		Long uid = user.getId();
		loc.setUid(uid);
		loc.setTime(new Date());

		Location cacheloc = locationService.getFromCache(uid);
		if (cacheloc == null) {
			locationService.saveOrUpdate(loc, user);
		}

		locationService.putToCache(loc);
		cacheTracePoint(loc);
		return new ApiResultServer();
	}

	// TODO 没有做安全限制，有权限泄露的危险
	@RequestMapping("/listbyuids.*")
	public ApiResultServer listByUids(Long[] uids) {
		List<Location> locationList = locationService.listByUids(Arrays.asList(uids));
		return new ApiResultServer(locationList);
	}

	@RequestMapping("/listnearby.*")
	public ApiResultServer getNearbyLocations(Integer sex, Long time, Double distance, Integer ageStart, Integer ageEnd,
			Integer page, Integer pageSize) {
		User user = UserUtils.getCurrentUser();
		Long uid = user.getId();

		Location curLoc = locationService.findByUid(uid);
		if (curLoc == null) {
			new ApiResultServer(Collections.EMPTY_LIST);
		}
		Date timeDate = null;
		if (time != null) {
			timeDate = new Date(System.currentTimeMillis() - time);
		}
		java.sql.Date birthStart = null, birthEnd = null;
		Long ayear = 1L * 365 * 24 * 60 * 60 * 1000;
		// 生日和年龄顺序是相反的
		if (ageEnd != null) {
			birthStart = new java.sql.Date(System.currentTimeMillis() - ageEnd * ayear);
		}
		if (ageStart != null) {
			birthEnd = new java.sql.Date(System.currentTimeMillis() - ageStart * ayear);
		}
		List<Location> locList = locationService.getNearBy(uid, curLoc.getLon(), curLoc.getLat(), timeDate, sex,
				distance, birthStart, birthEnd, (page - 1) * pageSize, pageSize);
		return new ApiResultServer(locList);
	}

	@ApiDoc({ "返回值", "uid,date,points,其中points的格式是一个数组，每个元素的格式是lat|lon|time,其中time的单位是秒，而非毫秒" })
	@RequestMapping("/listtrace.*")
	public ApiResultServer getTrace(Long uid, java.sql.Date date) {
		Trace paramTrace = new Trace(uid);
		paramTrace.setDate(date);
		List<Trace> trlist = traceService.findList(paramTrace);
		Trace cachTrace = traceService.getFromCache(paramTrace.getUid());
		if (cachTrace == null) {
			return new ApiResultServer(trlist);
		}
		// 注意，java.sql.date不能直接比较是否相等，要么转化后再比较，要么比较字符串
		if (paramTrace.getDate() == null || DateUtil.sameDay(paramTrace.getDate(), cachTrace.getDate())) {
			trlist.add(cachTrace);
		}
		return new ApiResultServer(trlist);
	}

	private void cacheTracePoint(Location loc) {// 缓存足迹点
		Trace trace = traceService.getFromCache(loc.getUid());
		if (trace == null) {
			trace = new Trace(loc.getUid());
			trace.setDate(new java.sql.Date(loc.getTime().getTime()));
		}
		synchronized (trace) {
			List<Location> points = trace.getPointsData();
			if (points.size() > 0) {
				Location lastLoc = points.get(points.size() - 1);
				double dist = GeoUtil.getDistance(lastLoc, loc);
				if (dist > 20) {// 小于10m的点无效
					points.add(loc);
				}
			} else {
				points.add(loc);
			}

			traceService.putToCache(trace);
			if (points.size() > 1) {
				Date timenow = points.get(0).getTime();
				Date timelast = points.get(points.size() - 1).getTime();
				// 如果隔天，那么就存入数据库一次
				if (!DateUtil.sameDay(timenow, timelast)) {
					trace.getPoints().remove(points.size() - 1);
					trace.setReason(TraceReason.DAYEND);
					traceService.save(trace);
				}
			}
		}
	}
}
